package com.yun.zhong.fu.sharecenter.config;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author RenPu
 * @Date 2020/12/29 11:52
 * @Version 1.0
 * @Description: 根据不同的所属的用户，就近原则调用集群进行服务实例：例如用户是在北京，
 *              有限调用的就是北京集群实例进行提供服务
 **/

@Slf4j
public class NacosSampleClusterWeightRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;


    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object key) {
        try {
            //获取集群的名称
            String clusterName = nacosDiscoveryProperties.getClusterName();

            BaseLoadBalancer loadBalancer = (BaseLoadBalancer)this.getLoadBalancer();

            //想要请求的微服务的名称
            String name = loadBalancer.getName();

            //实现负载均衡算法 拿到服务相关的API
            NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();

            //1:找到指定服务下的所有实例
            List<Instance> instances = namingService.selectInstances(name, true);

            //获取nacos元数据的方法
//            instances.get(0).getMetadata()

            //2:过滤出相同集群下的所有实例：例如A集群有2个实例，B集群有3个实例，进行归类
            List<Instance> sampleClusterinstance = instances.stream()
                    .filter(instance -> Objects.equals(instance.getClusterName(), clusterName))
                    .collect(Collectors.toList());
            //3：如果B是空，就选择A进行提供服务

            List<Instance> instanceToBeChosen= new ArrayList<>();

            if(CollectionUtils.isEmpty(sampleClusterinstance)){
                instanceToBeChosen=instances;
                log.warn("发生了跨集群的调用，name = {},clusterName = {},instance = {}",
                        name,
                        clusterName,
                        instances
                        );
            }else {
                instanceToBeChosen=sampleClusterinstance;
            }

            //4:基于权重的负载均衡，返回一个服务实例
            Instance hostByRandomWeight2 = ExtendsBaalancer.getHostByRandomWeight2(instanceToBeChosen);
            return new NacosServer(hostByRandomWeight2);
        } catch (NacosException e) {
            log.error("发生异常了！！！！");
            return null;
        }
    }
}

class ExtendsBaalancer extends Balancer{
    public static Instance getHostByRandomWeight2(List<Instance> instances){
        return getHostByRandomWeight(instances);
    }
}


